有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java单一责任原则与服务/存储库设计

我想知道如何在下面的例子中最好地分离责任

有一个Foo对象,它有一些id和一些reallySecretImportantData字段。Id是引用对象的简单标识符,而reallySecretImportantData是数据库中应该加密的数据,因为在本例中,数据库是唯一易受攻击的点

现在,如果我们有一个FooService方法void storeFoo(Foo foo)Foo readFoo(Id id)

我们还有一个FooRepository,它有标准的CRUD方法,在数据库中存储Foo对象

现在,由于我想保存reallySecretImportantData加密,我必须在某处加密并解密它

由于FooRepository的职责不应包括加密操作,因此逻辑位置为FooService

现在,如果我在某个开发环境中,我希望,对于dev&;测试目的是将reallySecretImportantData保存为纯文本

如果我使用某种DI,我可以编写我的服务的两个实现,一个用于prod,另一个用于dev/test,只需将DI配置为在生产环境中使用prod,在dev&;中使用dev/test;测试环境

现在,如果在不久的将来出现更改reallySecretImportantData存储方式的请求,我可以简单地编写服务的另一个实现,并使用我的DI框架注入它

这种简单的设计对于当前的模型箱来说足够好吗


共 (2) 个答案

  1. # 1 楼答案

    你的设计让我想起strategy pattern.FooService可以被视为一个策略接口

    但是我更喜欢向这个接口添加encrypt()decrypt()方法,而不是store()read()。我们可以把它命名为FooCryptoStrategy

    此外,FooRepository可以用FooCryptoStrategy对象构造。 因此,您可以不考虑加密问题而对Foo对象进行CRUD。 您可以为发布和测试创建几个FooCryptoStrategy实现。甚至你也可以实现一个NonCryptoStrategy

    总之,使用策略模式,我们可以将一个职责分配给一个类:
    Foo:存储数据
    FooCryptoStrategy:加密和解密Foo对象
    FooRepository:使Foo对象持久化
    控制器类:创建具体的FooCryptoStrategyFooRepository对象

  2. # 2 楼答案

    你为什么需要“服务”

    考虑一个知道如何En/De/Curpt的^ {< CD1>}对象,以及一个处理持久性的数据管理对象。

    通过使用一个通用接口实现加密算法,使您的功能“可插拔”,例如IcenRypt。例如,你可能有一个AES加密机和一个TestPlainEncryptor

    // simple non-dependency-injection example    
    Secret encrypted = new Secret(new AesEncryptor, "key", "my secret stuff");
    new SecretDM().Save(s);
    
    Secret retrieved = new SecretDM().Get("key");
    // println(retrieved.Decrypt());